package com.xz.process.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.apply.domain.PurchaseApply;
import com.xz.apply.domain.PurchaseProductApply;
import com.xz.apply.service.IPurchaseApplyService;
import com.xz.common.core.domain.AjaxResult;
import com.xz.common.exception.ServiceException;
import com.xz.common.utils.DateUtils;
import com.xz.common.utils.RedisCode;
import com.xz.common.utils.SecurityUtils;
import com.xz.common.utils.StringUtils;
import com.xz.log.domain.OperationLog;
import com.xz.log.service.IOperationLogService;
import com.xz.message.service.ISysTenantNotifyItemService;
import com.xz.message.service.ISysTenantNotifyParamService;
import com.xz.optometry.service.IOptometryService;
import com.xz.optometry.vo.OptometryInfoVo;
import com.xz.patient.domain.PatientInfo;
import com.xz.patient.mapper.PatientInfoMapper;
import com.xz.process.domain.ProcessOrder;
import com.xz.process.domain.ProcessOrderItem;
import com.xz.process.dto.ProcessOrderFinishedDto;
import com.xz.process.mapper.ProcessOrderMapper;
import com.xz.process.service.IProcessOrderItemService;
import com.xz.process.service.IProcessOrderService;
import com.xz.process.vo.MaterialRequisitionProcessingVo;
import com.xz.process.vo.ProcessOrderExportVo;
import com.xz.process.vo.ProcessOrderInfoVo;
import com.xz.process.vo.ProcessOrderVo;
import com.xz.purchase.domain.PurchaseProduct;
import com.xz.purchase.mapper.PurchaseProductMapper;
import com.xz.purchase.vo.ChoosePurchaseProductVo;
import com.xz.repertory.service.IRepertoryFlowService;
import com.xz.sales.domain.SalesOrder;
import com.xz.sales.domain.SalesOrderDetail;
import com.xz.sales.domain.SalesPurchase;
import com.xz.sales.mapper.SalesOrderDetailMapper;
import com.xz.sales.mapper.SalesOrderMapper;
import com.xz.sales.mapper.SalesPurchaseMapper;
import com.xz.sales.service.ISalesOrderDetailService;
import com.xz.sales.service.ISalesOrderService;
import com.xz.sales.util.ProcessOrderUtil;
import com.xz.warehouse.domain.Warehouse;
import com.xz.warehouse.service.IWarehouseService;
import common.ECDateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 加工单Service业务层处理
 *
 * @author xz
 * @date 2024-02-04
 */
@Service
public class ProcessOrderServiceImpl extends ServiceImpl<ProcessOrderMapper, ProcessOrder> implements IProcessOrderService {
    @Autowired
    private ProcessOrderMapper processOrderMapper;
    @Autowired
    private IProcessOrderItemService iProcessOrderItemService;
    @Autowired
    private IWarehouseService iWarehouseService;
    @Autowired
    private IOptometryService iOptometryService;
    @Autowired
    private ISalesOrderService iSalesOrderService;
    @Autowired
    private IOperationLogService operationLogService;
    @Autowired
    private ISysTenantNotifyItemService iSysTenantNotifyItemService;
    @Autowired
    private PurchaseProductMapper purchaseProductMapper;
    @Autowired
    private IPurchaseApplyService iPurchaseApplyService;
    @Autowired
    private ISalesOrderDetailService iSalesOrderDetailService;
    @Autowired
    private IRepertoryFlowService iRepertoryFlowService;
    @Autowired
    private SalesPurchaseMapper salesPurchaseMapper;
    @Autowired
    private SalesOrderDetailMapper salesOrderDetailMapper;
    @Autowired
    private SalesOrderMapper salesOrderMapper;
    @Autowired
    private ISysTenantNotifyParamService sysTenantNotifyParamService;
    @Resource
    private PatientInfoMapper patientInfoMapper;

    private static final Logger log = LoggerFactory.getLogger(ProcessOrderServiceImpl.class);

    /**
     * 查询加工单
     *
     * @param id 加工单主键
     * @return 加工单
     */
    @Override
    public ProcessOrderInfoVo selectProcessOrderById(Long id) {
        ProcessOrderInfoVo processOrderInfoVo = processOrderMapper.selectProcessOrderById(id);
        if(Objects.isNull(processOrderInfoVo)){
            throw new ServiceException("加工单不存在");
        }
        //销售订单信息
        Long salesOrderId = processOrderInfoVo.getSalesOrderId();
        if(salesOrderId!=null){
            SalesOrder salesOrder = iSalesOrderService.getById(salesOrderId);
            if(Objects.isNull(salesOrder)){
                throw new ServiceException("加工单不存在");
            }
            OptometryInfoVo optometryInfoVo = iOptometryService.selectProcessOptometryById(salesOrder.getOptometryId());
            if(Objects.nonNull(optometryInfoVo)){
                processOrderInfoVo.setOptometryInfoVo(optometryInfoVo);
            }
        }
        return processOrderInfoVo;
    }

    /**
     * 查询加工单列表
     *
     * @param processOrder 加工单
     * @return 加工单
     */
    @Override
    public List<ProcessOrderVo> selectProcessOrderList(ProcessOrder processOrder) {
        return processOrderMapper.selectProcessOrderList(processOrder);
    }
    /**
     * 查询加工单列表(导出)
     *
     * @param processOrder 加工单
     * @return 加工单
     */
    @Override
    public List<ProcessOrderExportVo> selectProcessOrderExportList(ProcessOrder processOrder) {
        return processOrderMapper.selectProcessOrderExportList(processOrder);
    }

    /**
     * 新增加工单
     *
     * @param processOrder 加工单
     * @return 结果
     */
    @Override
    public boolean insertProcessOrder(ProcessOrder processOrder) {
        List<ProcessOrderItem> processOrderItemList = processOrder.getProcessOrderItemList();
        if(CollectionUtils.isEmpty(processOrderItemList)){
            throw new ServiceException("参数不能为空");
        }
        processOrder.setProcessNo(RedisCode.getCode("JG"));
        processOrder.setCreateTime(DateUtils.getNowDate());
        processOrder.setCreateBy(SecurityUtils.getUserId());
        processOrder.setTenantId(SecurityUtils.getLoginUser().getTenantId());
        if(Objects.isNull(processOrder.getProcessingStatus())){
            processOrder.setProcessingStatus(2);
        }
        int insertProcessOrder = processOrderMapper.insertProcessOrder(processOrder);
        if(insertProcessOrder>0){
            processOrderItemList.stream().forEach(i->{
                i.setProcessOrderId(processOrder.getId());
                i.setSalesOrderId(processOrder.getSalesOrderId());
                if(Objects.isNull(i.getStatus())){
                    if(i.getStatus()!=2 && i.getWarehouseId()!=null){
                        Warehouse warehouse = iWarehouseService.getById(i.getWarehouseId());
                        if(warehouse.getIsShare()==1){
                            i.setStatus(3);
                        }
                    }else{
                        i.setStatus(2);
                    }
                }
            });
            boolean savedBatch = iProcessOrderItemService.saveBatch(processOrderItemList);
            if(!savedBatch){
                throw new ServiceException("新增加工单失败");
            }
            operationLogService.insertOperationLog(
                    new OperationLog(processOrder.getId()+"",3,processOrder.getTenantId(),
                            SecurityUtils.getUserId(),SecurityUtils.getUsername(), ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，创建加工单"));
            return true;
        }

        return false;
    }

    /**
     * 修改加工单
     *
     * @param processOrder 加工单
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateProcessOrder(ProcessOrder processOrder) {
        ProcessOrder order = processOrderMapper.selectById(processOrder.getId());
        processOrder.setUpdateTime(DateUtils.getNowDate());
        processOrder.setUpdateBy(SecurityUtils.getUserId());
            String note="操作成功";
            //原状态
            Integer processingStatus = order.getProcessingStatus();
            //操作状态
            Integer status = processOrder.getProcessingStatus();
            //1.备货中 2.待领料 3.加工中 4.待质检 5.质检不合格 6.加工完成 7.已完成 8.取消加工 9.已配送
            if(status==3){
                List<ProcessOrderItem> orderItemList = iProcessOrderItemService.list(new QueryWrapper<ProcessOrderItem>().eq("process_order_id", processOrder.getId()).in("status", 1,3,6));
                orderItemList.stream().forEach(i->i.setStatus(4));
                boolean updateBatchById = iProcessOrderItemService.updateBatchById(orderItemList);
                if(!updateBatchById){
                    throw new ServiceException("操作失败");
                }
                if(processingStatus==1){
                    note="签收成功";
                }
                if(processingStatus==2){
                    note="领料成功";
                }
            }else if(status==4){
                processOrder.setProcessTime(new Date());
                note="加工完成";
            }else if(status==5){
                processOrder.setQualityInspectorTime(new Date());
                processOrder.setQualityInspectorId(SecurityUtils.getUserId());
                processOrder.setQualityInspector(SecurityUtils.getUsername());
                processOrder.setQualityInspectorNote("质检不合格");
                note="质检不合格";
            }else if(status==6){
                processOrder.setQualityInspectorTime(new Date());
                processOrder.setQualityInspectorId(SecurityUtils.getUserId());
                processOrder.setQualityInspector(SecurityUtils.getUsername());
                processOrder.setQualityInspectorNote("质检合格");
                List<ProcessOrderItem> orderItemList = iProcessOrderItemService.list(new QueryWrapper<ProcessOrderItem>().eq("process_order_id", processOrder.getId()).eq("status",4));
                orderItemList.stream().forEach(i->{
                    i.setStatus(7);
                });
                boolean updateBatchById = iProcessOrderItemService.updateBatchById(orderItemList);
                if(!updateBatchById){
                    throw new ServiceException("操作失败");
                }
                note="质检完成";
            }else if(status==8){
                List<ProcessOrderItem> orderItemList = iProcessOrderItemService.list(new QueryWrapper<ProcessOrderItem>().eq("process_order_id", processOrder.getId()).in("status",4,6));
                if(CollectionUtils.isEmpty(orderItemList)){
                    throw new ServiceException("操作失败");
                }
                orderItemList.stream().forEach(i->i.setStatus(3));
                boolean updateBatchById = iProcessOrderItemService.updateBatchById(orderItemList);
                if(!updateBatchById){
                    throw new ServiceException("操作失败");
                }
                note="取消加工";
                processOrder.setProcessingStatus(2);
                //修改销售单商品状态
                orderItemList.stream().forEach(i->{
                    SalesOrderDetail detailServiceById = iSalesOrderDetailService.getById(i.getSalesOrderDetailId());
                    if(Objects.nonNull(detailServiceById)){
                        detailServiceById.setProductStatus(8);
                        detailServiceById.setUpdateBy(SecurityUtils.getUserId());
                        detailServiceById.setUpdateTime(new Date());
                        iSalesOrderDetailService.updateSalesOrderDetail(detailServiceById);
                    }
                });
            }
            int updateProcessOrder = processOrderMapper.updateProcessOrder(processOrder);
            if(updateProcessOrder==0){
                return AjaxResult.error("操作失败");
            }
            operationLogService.insertOperationLog(
                    new OperationLog(processOrder.getId()+"",3,processOrder.getTenantId(),
                            SecurityUtils.getUserId(),SecurityUtils.getUsername(), ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，"+note));
            return AjaxResult.success("操作成功");

    }

    /**
     * 批量删除加工单
     *
     * @param ids 需要删除的加工单主键
     * @return 结果
     */
    @Override
    public int deleteProcessOrderByIds(Long[] ids) {
        return processOrderMapper.deleteProcessOrderByIds(ids);
    }

    /**
     * 删除加工单信息
     *
     * @param id 加工单主键
     * @return 结果
     */
    @Override
    public int deleteProcessOrderById(Long id) {
        return processOrderMapper.deleteProcessOrderById(id);
    }

    /**
     * 签收
     * @param processOrderItem
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult materielSigner(ProcessOrderItem processOrderItem) {
        ProcessOrderItem orderItem = iProcessOrderItemService.getById(processOrderItem.getId());
        if(Objects.isNull(orderItem)){
            return AjaxResult.error("签收失败");
        }
        orderItem.setStatus(3);
        orderItem.setSigner(SecurityUtils.getUsername());
        orderItem.setSignerTime(new Date());
        boolean updateById = iProcessOrderItemService.updateById(orderItem);
        if(!updateById){
            return AjaxResult.error("签收失败");
        }
        int count = iProcessOrderItemService.count(new QueryWrapper<ProcessOrderItem>().eq("process_order_id", orderItem.getProcessOrderId()).in("status", 1, 2));
        if(count==0){
            int updateProcessOrderStatus = baseMapper.updateProcessOrderStatus(orderItem.getProcessOrderId(), 2);
            if(updateProcessOrderStatus==0){
                throw new ServiceException("签收失败");
            }
        }
        //更新销售单状态
        SalesOrderDetail salesOrderDetail =new SalesOrderDetail();
        salesOrderDetail.setId(orderItem.getSalesOrderDetailId());
        salesOrderDetail.setProductStatus(8);
        iSalesOrderDetailService.updateSalesOrderDetail(salesOrderDetail);
        operationLogService.insertOperationLog(
                new OperationLog(orderItem.getProcessOrderId()+"",3,SecurityUtils.getLoginUser().getTenantId(),
                        SecurityUtils.getUserId(),SecurityUtils.getUsername(), SecurityUtils.getUsername()+","+ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，签收物料"+processOrderItem.getProductName()));

        return AjaxResult.success("签收成功");
    }

    /**
     * 客户自备镜框签收
     * @param processOrder
     * @return
     */
    @Override
    public AjaxResult eyeglassFramesSigner(ProcessOrder processOrder) {
        ProcessOrder selectedById = baseMapper.selectById(processOrder.getId());
        if(Objects.isNull(selectedById)){
            return AjaxResult.error("签收失败");
        }
        selectedById.setProvideOneself(1);
        selectedById.setSigner(SecurityUtils.getUsername());
        selectedById.setSignerTime(new Date());
        selectedById.setUpdateBy(SecurityUtils.getUserId());
        selectedById.setUpdateTime(new Date());
        baseMapper.updateProcessOrder(selectedById);
        operationLogService.insertOperationLog(
                new OperationLog(selectedById.getId()+"",3,SecurityUtils.getLoginUser().getTenantId(),
                        SecurityUtils.getUserId(),SecurityUtils.getUsername(), SecurityUtils.getUsername()+","+ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，签收客户自备镜框"));

        return AjaxResult.success("签收成功");
    }

    /**
     * 加工单-客户自备镜架·短信通知
     * eyeglassFramesSmsNotification
     * @param processOrder
     * @return
     */
    @Override
    public AjaxResult eyeglassFramesSmsNotification(ProcessOrder processOrder) {
        ProcessOrder selectedById = baseMapper.selectById(processOrder.getId());
        if(Objects.isNull(selectedById)){
            return AjaxResult.error("通知失败");
        }
        selectedById.setNotifyCustomerTime(new Date());
        baseMapper.updateById(selectedById);
        iSysTenantNotifyItemService.sendMachiningCenterMsg(selectedById,6,SecurityUtils.getLoginUser().getUser());
        operationLogService.insertOperationLog(
                new OperationLog(selectedById.getId()+"",3,SecurityUtils.getLoginUser().getTenantId(),
                        SecurityUtils.getUserId(),SecurityUtils.getUsername(), SecurityUtils.getUsername()+","+ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，短信通知客户邮寄镜框"));

        return AjaxResult.success("通知成功");
    }

    /**
     * 查看短信模板
     * @param orderId
     * @param msgType
     * @return
     */
    @Override
    public AjaxResult getSmsNotificationContext(Long orderId,Integer msgType) {

        ProcessOrder order = baseMapper.selectById(orderId);
        if(null == order){
            return AjaxResult.error("");
        }
        String context = iSysTenantNotifyItemService.selecContexttByType(msgType);
        if(!StringUtils.isEmpty(context)){
            Map<String, String> param = sysTenantNotifyParamService.getForProcessOrder(order, msgType);
            context = sysTenantNotifyParamService.replaceTplContent(context,param);
        }
        return AjaxResult.success(context);
    }

    /**
     * 领料加工
     * @param processingVo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult materialRequisitionProcessing(MaterialRequisitionProcessingVo processingVo) {
        ProcessOrder selectedById = baseMapper.selectById(processingVo.getId());
        if(Objects.isNull(selectedById)){
            return AjaxResult.error("领料失败");
        }
        boolean flag=false;
        if(processingVo.getType()==2){
            int updateProcessOrderItemById = iProcessOrderItemService.updateProcessOrderItemById(processingVo.getItemId(), 4);
            if(updateProcessOrderItemById==0){
                return AjaxResult.error("领料失败");
            }
            int count = iProcessOrderItemService.count(new QueryWrapper<ProcessOrderItem>().eq("sales_order_id", processingVo.getId()).in("status", 1, 3));
            if(count==0){
                flag=true;
            }
            ProcessOrderItem processOrderItem = iProcessOrderItemService.getById(processingVo.getItemId());
            if(Objects.isNull(processOrderItem)){
                throw new ServiceException("领料失败");
            }
            //更新销售单状态
            SalesOrderDetail salesOrderDetail =new SalesOrderDetail();
            salesOrderDetail.setId(processOrderItem.getSalesOrderDetailId());
            salesOrderDetail.setProductStatus(9);
            iSalesOrderDetailService.updateSalesOrderDetail(salesOrderDetail);
        }else{
            List<ProcessOrderItem> list = iProcessOrderItemService.list(new QueryWrapper<ProcessOrderItem>().eq("process_order_id", processingVo.getId()).in("status", 1, 3));
            if(!CollectionUtils.isEmpty(list)){
                list.stream().forEach(i->{
                    i.setStatus(4);
                    //更新销售单状态
                    SalesOrderDetail salesOrderDetail =new SalesOrderDetail();
                    salesOrderDetail.setId(i.getSalesOrderDetailId());
                    salesOrderDetail.setProductStatus(9);
                    iSalesOrderDetailService.updateSalesOrderDetail(salesOrderDetail);
                });
                iProcessOrderItemService.updateBatchById(list);
                flag=true;
            }
        }
        if(flag){
            selectedById.setProcessingStatus(3);
            selectedById.setUpdateBy(SecurityUtils.getUserId());
            selectedById.setUpdateTime(new Date());
            selectedById.setProcessMasterId(SecurityUtils.getUserId());
            selectedById.setProcessMaster(SecurityUtils.getUsername());
            baseMapper.updateProcessOrder(selectedById);
        }
        operationLogService.insertOperationLog(
                new OperationLog(selectedById.getId()+"",3,SecurityUtils.getLoginUser().getTenantId(),
                        SecurityUtils.getUserId(),SecurityUtils.getUsername(), SecurityUtils.getUsername()+","+ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，领料成功"));

        return flag?AjaxResult.success("领料成功"):AjaxResult.error("无待领料商品");
    }

    /**
     * 报损
     * @param orderItem
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult reportDamage(ProcessOrderItem orderItem) {
        ProcessOrderItem processOrderItem = iProcessOrderItemService.getById(orderItem.getId());
        if(Objects.isNull(processOrderItem)){
            return AjaxResult.error("报损失败");
        }
        //校验仓库是否有库存
        PurchaseProduct purchaseProduct =new PurchaseProduct();
        purchaseProduct.setProductName(processOrderItem.getProductName());
        purchaseProduct.setProductParam(processOrderItem.getProductParam());
        SalesOrderDetail detailServiceById = iSalesOrderDetailService.getById(processOrderItem.getSalesOrderDetailId());
        if(Objects.nonNull(detailServiceById)){
            purchaseProduct.setBatchNumber(detailServiceById.getBatchNumber());
            purchaseProduct.setWarehouseId(detailServiceById.getWarehouseId());
        }
        processOrderItem.setStatus(9);
        boolean updateById = iProcessOrderItemService.updateById(processOrderItem);
        if(!updateById){
            return AjaxResult.error("报损失败");
        }
        List<ChoosePurchaseProductVo> findList = purchaseProductMapper.findByNameAndParam(purchaseProduct);
        processOrderItem.setStatus(6);
        processOrderItem.setRemark("报损补充");
        processOrderItem.setId(null);
        if(CollectionUtils.isEmpty(findList)){
            processOrderItem.setStatus(5);
        }
        int insertProcessOrderItem = iProcessOrderItemService.insertProcessOrderItem(processOrderItem);
        if(insertProcessOrderItem==0){
            throw new ServiceException("报损失败");
        }
        operationLogService.insertOperationLog(
                new OperationLog(orderItem.getProcessOrderId()+"",3,SecurityUtils.getLoginUser().getTenantId(),
                        SecurityUtils.getUserId(),SecurityUtils.getUsername(), SecurityUtils.getUsername()+","+ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，报损成功"));

        return AjaxResult.success("报损成功");
    }

    /**
     * 成品配送
     * @param orderRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult finishedProductDistribution(ProcessOrderFinishedDto orderRequest) {

        ProcessOrder processOrder = baseMapper.selectById(orderRequest.getId());
        if (Objects.isNull(processOrder)) {
            return AjaxResult.error("加工单不存在。");
        }
        processOrder.setTrackingNumber(orderRequest.getTrackingNumber());
        // [加工单]状态变更为：已配送
        processOrder.setProcessingStatus(9);
        processOrder.setDeliveryTime(new Date());
        // 非业务字段赋值
        processOrder.setUpdateBy(SecurityUtils.getUserId());
        processOrder.setUpdateTime(new Date());
        // 更新[加工单]
        baseMapper.updateProcessOrder(processOrder);
        // 检索[加工单]明细
        List<ProcessOrderItem> processOrderItemList = iProcessOrderItemService.list(new QueryWrapper<ProcessOrderItem>().eq(
                "process_order_id", orderRequest.getId()));
        if (CollectionUtils.isEmpty(processOrderItemList)) {
            throw new ServiceException("加工单明细更新失败,查询加工单商品数量为0。");
        }
        // 根据[加工单]的销售单id检索[销售单]
        SalesOrder salesOrder = iSalesOrderService.getById(processOrder.getSalesOrderId());
        if (Objects.isNull(salesOrder)) {
            throw new ServiceException("加工单明细更新失败,加工单对应的销售单不存在。");
        }
        //开始根据[加工单明细]逐一更新数据
        for (ProcessOrderItem processOrderItem : processOrderItemList) {
            // 检索[销售单商品明细]
            SalesOrderDetail salesDetail = iSalesOrderDetailService.getById(processOrderItem.getSalesOrderDetailId());
            if (Objects.isNull(salesDetail)) {
                String message = String.format("加工单明细更新失败,商品[%s]无法找到对应的销售单商品。",processOrderItem.getProductName());
                throw new ServiceException(message);
            }
            // 根据交付方式，改变[销售单商品明细]的状态。
            // 如果是[加工单]的交付方式为1（门店自提）时， 则[销售单商品明细]状态为10（待签收）;
            // 如果是[加工单]的交付方式为2（邮寄）时， 则[销售单商品明细]状态为12（已交付），并且对交付时间赋值;
            salesDetail.setProcessDeliveryTime(new Date());
            if (processOrder.getDeliveryMethod() == 1) {
                salesDetail.setProductStatus(10);
            }else{
                salesDetail.setProductStatus(12);
                salesDetail.setDeliveryTime(new Date());
            }
            salesDetail.setDeliveryDeptId(SecurityUtils.getDeptId());
            // 更新[销售单明细]
            int isDetailUpdated = iSalesOrderDetailService.updateSalesOrderDetail(salesDetail);
            if (isDetailUpdated == 0) {
                String message = String.format("加工单明细更新失败,商品[%s]无法更新对应的销售单商品。",processOrderItem.getProductName());
                throw new ServiceException(message);
            }
            // 如果[加工单]交付方式为邮寄时，说明该商品交付完成，需要额外处理一些业务
            if (processOrder.getDeliveryMethod() == 2) {
                //生成销售订单的交付流水
                saveFlowForDelivery(salesOrder, salesDetail);
            }
        }
        // 遍历更新销售单状态
        List<SalesOrderDetail> salesOrderDetails = salesOrderDetailMapper.selectBySalesId(processOrder.getSalesOrderId());
        Integer orderStatus = ProcessOrderUtil.processOrderStatusByDetails(salesOrderDetails);
        salesOrderMapper.updateOrderStatus(processOrder.getSalesOrderId(), orderStatus);
        // 新增加工单的操作记录
        operationLogService.insertOperationLog(
                new OperationLog(processOrder.getId() + "", 3, SecurityUtils.getLoginUser().getTenantId(),
                        SecurityUtils.getUserId(), SecurityUtils.getUsername(),
                        SecurityUtils.getUsername() + "," + ECDateUtils.formatDate(new Date(), "yyyy-MM-dd") + "，配送成功"));

        // 如果寄件方式是客户自提，则无需发送短信；反之则需要
        if (processOrder.getDeliveryMethod().intValue() == 2) {
            // 加工单交付·短信通知
            iSysTenantNotifyItemService.sendMachiningCenterMsg(processOrder,7,SecurityUtils.getLoginUser().getUser());
        }
        return AjaxResult.success("配送成功");
    }

    /**
     * 生成销售订单的交付流水
     * @param salesOrder 销售单
     * @param salesDetail 销售单明细
     */
    private void saveFlowForDelivery(SalesOrder salesOrder, SalesOrderDetail salesDetail) {

        // [销售采购记录]左连接[采购商品明细]查询，然后只为了list的size???
        SalesPurchase salesPurchase = new SalesPurchase();
        salesPurchase.setSalesId(salesOrder.getId());
        salesPurchase.setDetailId(salesDetail.getId());
        List<PurchaseProduct> purchaseProducts = salesPurchaseMapper.selectPurchaseList(salesPurchase);
        //查询[采购商品明细]数据
        //PurchaseProduct queryProductParam = new PurchaseProduct();
       // BeanUtils.copyProperties(salesDetail, queryProductParam);
        //List<PurchaseProduct> purchaseProductList = purchaseProductMapper.getSalesListByParam(queryProductParam);
        // 构建流水信息。
       // List<PurchaseProduct> purchaseProductsList = iRepertoryFlowService.convertFlowData(purchaseProductList, salesDetail.getSellingNum(), salesOrder.getSalesNo(), salesDetail.getId());
        // [销售单商品明细]当前的金额 -- 用于后续分摊计算最后一笔数据，避免金额因为四舍五入有误差。
        BigDecimal detailTotal = salesDetail.getSubtotal();
        // 商品单价 = 小计/销售数量
        BigDecimal unitPrice = detailTotal.divide(BigDecimal.valueOf(salesDetail.getSellingNum()), 4,BigDecimal.ROUND_HALF_UP);
        // 累计总价
        BigDecimal summaryTotal = new BigDecimal("0.00");
        // 开始迭代
        for (int i = 0; i < purchaseProducts.size(); i++) {
            PurchaseProduct purchaseProduct = purchaseProducts.get(i);
            purchaseProduct.setPurchaseNumber(salesOrder.getSalesNo());
            purchaseProduct.setBusinessId(salesDetail.getId());
            purchaseProduct.setMemberId(salesOrder.getPatientId());
            purchaseProduct.setMemberName(salesOrder.getPatientName());
            purchaseProduct.setPrice(salesDetail.getSellingPrice());
            purchaseProduct.setRemark(salesDetail.getRemark());
            purchaseProduct.setDeptId(salesOrder.getDeptId());

            // 默认采用当前时间，如果存在交付时间，则采用交付时间。
            purchaseProduct.setCreateTime(new Date());
            if (Objects.nonNull(salesDetail.getDeliveryTime())) {
                purchaseProduct.setCreateTime(salesDetail.getDeliveryTime());
            }
            // 最后一笔数据采用的计算方式为：最后一笔数据小计 = [销售单商品明细]当前的金额 - 累计总价
            if (i == purchaseProducts.size() - 1) {
                BigDecimal subtract = detailTotal.subtract(summaryTotal);
                purchaseProduct.setSubtotal(subtract);
                break;
            }
            // 除最后一笔以外，计算其余的单项金额（即：单项金额 = 商品数量 * 商品单价）
            BigDecimal quantity = BigDecimal.valueOf(purchaseProduct.getInventoryQuantity());
            BigDecimal subtotal = unitPrice.multiply(quantity);
            purchaseProduct.setSubtotal(subtotal);
            // 单项金额加入总金额中,用于最后一笔分摊数据计算。
            summaryTotal = summaryTotal.add(subtotal);
        }

        // 保存流水记录
        if (!CollectionUtils.isEmpty(purchaseProducts)) {
            log.info("----------"+ JSON.toJSONString(purchaseProducts, SerializerFeature.PrettyFormat));
            boolean repertoryFlow = iRepertoryFlowService.saveRepertoryFlow(purchaseProducts, 2, 10);
            if (!repertoryFlow) {
                String message = String.format("销售单[%s]流水生成失败",salesOrder.getSalesNo());
                throw new ServiceException(message);
            }
        }
    }

    /**
     * 变更加工师
     * @param processOrder
     * @return
     */
    @Override
    public AjaxResult changeMachinist(ProcessOrder processOrder) {
        ProcessOrder selectedById = baseMapper.selectById(processOrder.getId());
        if(Objects.isNull(selectedById)){
            return AjaxResult.error("变更失败");
        }
        processOrder.setUpdateBy(SecurityUtils.getUserId());
        processOrder.setUpdateTime(new Date());
        int updateProcessOrder = baseMapper.updateProcessOrder(processOrder);
        if(updateProcessOrder>0){
            operationLogService.insertOperationLog(
                    new OperationLog(processOrder.getId()+"",3,SecurityUtils.getLoginUser().getTenantId(),
                            SecurityUtils.getUserId(),SecurityUtils.getUsername(), SecurityUtils.getUsername()+","+ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，将加工师【"+selectedById.getProcessMaster()+"】变更为【"+processOrder.getProcessMaster()+"】"));

        }
        return AjaxResult.success("变更成功");
    }

    /**
     * 定制采购
     * @param orderItem
     * @return
     */
    @Override
    public AjaxResult customPurchasing(ProcessOrderItem orderItem) {
        ProcessOrderItem processOrderItem = iProcessOrderItemService.getById(orderItem.getId());
        if(Objects.isNull(processOrderItem)){
            return AjaxResult.error("采购失败");
        }
        ProcessOrder selectedById = baseMapper.selectById(processOrderItem.getProcessOrderId());
        if(Objects.isNull(selectedById)){
            return AjaxResult.error("采购失败");
        }
        //销售单号
        SalesOrder salesOrder = iSalesOrderService.getById(selectedById.getSalesOrderId());
        if(Objects.isNull(selectedById)){
            return AjaxResult.error("采购失败");
        }
        PurchaseApply purchaseApply=new PurchaseApply();
        purchaseApply.setWarehouseId(processOrderItem.getWarehouseId());
        purchaseApply.setWarehouseName(processOrderItem.getWarehouseName());
        purchaseApply.setStatus(2);
        purchaseApply.setDeptId(selectedById.getSalesDeptId());
        purchaseApply.setApplyNum(1);
        purchaseApply.setProductApplyType(2);
        purchaseApply.setBizId(processOrderItem.getId());
        purchaseApply.setBizNo(salesOrder.getSalesNo());
        purchaseApply.setRemark("加工报损定制采购");
        List<PurchaseProductApply> productApplyList =new ArrayList<>();
        PurchaseProductApply purchaseProductApply=new PurchaseProductApply();
        purchaseProductApply.setApplyNum(1);
        PurchaseProduct queryProductParam = new PurchaseProduct();
        BeanUtils.copyProperties(processOrderItem,queryProductParam);
        List<PurchaseProduct> purchaseProductList = purchaseProductMapper.getPurchaseProductListByParam(queryProductParam);
        if(CollectionUtils.isEmpty(purchaseProductList)){
            return AjaxResult.error("采购失败");
        }
        PurchaseProduct purchaseProduct = purchaseProductList.get(0);
        purchaseProductApply.setProductName(purchaseProduct.getProductName());
        purchaseProductApply.setProductParam(purchaseProduct.getProductParam());
        purchaseProductApply.setProductEncoded(purchaseProduct.getProductEncoded());
        purchaseProductApply.setUnit(purchaseProduct.getUnit());
        purchaseProductApply.setProductId(purchaseProduct.getProductId());
        purchaseProductApply.setRemark("加工报损定制采购");
        productApplyList.add(purchaseProductApply);
        purchaseApply.setProductApplyList(productApplyList);
        AjaxResult ajaxResult = iPurchaseApplyService.insertPurchaseApply(purchaseApply);
        String string = String.valueOf(ajaxResult.get("code"));
        if("200".equals(string)){
            processOrderItem.setStatus(2);
            iProcessOrderItemService.updateProcessOrderItem(processOrderItem);
           return AjaxResult.success("采购发起成功");
        }
        return AjaxResult.error("采购失败");
    }

    /**
     * 定制采购
     * @param orderDetailList
     * @return
     */
    @Override
    public AjaxResult salesCustomPurchasing(List<SalesOrderDetail> orderDetailList) {
        //销售单号
        SalesOrder salesOrder = iSalesOrderService.getById(orderDetailList.get(0).getSalesId());
        if(Objects.isNull(salesOrder)){
            return AjaxResult.error("采购失败");
        }
        for (SalesOrderDetail salesOrderDetail:orderDetailList) {

            PurchaseApply purchaseApply=new PurchaseApply();
            purchaseApply.setWarehouseId(salesOrderDetail.getWarehouseId());
            purchaseApply.setWarehouseName(salesOrderDetail.getWarehouseName());
            purchaseApply.setStatus(2);
            purchaseApply.setDeptId(salesOrder.getDeptId());
            purchaseApply.setApplyNum(salesOrderDetail.getSellingNum());
            purchaseApply.setProductApplyType(3);
            purchaseApply.setBizId(salesOrderDetail.getId());
            purchaseApply.setBizNo(salesOrder.getSalesNo());
            List<PurchaseProductApply> productApplyList =new ArrayList<>();
            PurchaseProductApply purchaseProductApply=new PurchaseProductApply();
            purchaseProductApply.setApplyNum(salesOrderDetail.getSellingNum());
            PurchaseProduct queryProductParam = new PurchaseProduct();
            BeanUtils.copyProperties(salesOrderDetail,queryProductParam);
            List<PurchaseProduct> purchaseProductList = purchaseProductMapper.getPurchaseProductListByParam(queryProductParam);
            if(CollectionUtils.isEmpty(purchaseProductList)){
                return AjaxResult.error("采购失败！");
            }
            PurchaseProduct purchaseProduct = purchaseProductList.get(0);
            purchaseProductApply.setProductName(purchaseProduct.getProductName());
            purchaseProductApply.setProductParam(purchaseProduct.getProductParam());
            purchaseProductApply.setProductEncoded(purchaseProduct.getProductEncoded());
            purchaseProductApply.setUnit(purchaseProduct.getUnit());
            purchaseProductApply.setProductId(purchaseProduct.getProductId());
            productApplyList.add(purchaseProductApply);
            purchaseApply.setProductApplyList(productApplyList);
            AjaxResult ajaxResult = iPurchaseApplyService.insertPurchaseApply(purchaseApply);
            String string = String.valueOf(ajaxResult.get("code"));
            if(!"200".equals(string)){
                return AjaxResult.success("采购失败！");
            }
        }
        return AjaxResult.success("采购成功！");
    }
}
